﻿#include "config.h"
#include "crc.h"
#include <QtCore/QDebug>

//构造函数
Config::Config(ConnectThread *connectThread) :
	_connectThread(connectThread) {
	_root = newTree(nullptr);

	//建立叶子的list
	//接口设置页
	JsonDecode::appendJsonDir(_root, "/interface/", new JsonDirContent("baudrate", &_baudrate, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/interface/", new JsonDirContent("broadcastID", &_broadcastID, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/interface/", new JsonDirContent("settingID", &_receiveID, QJsonValue::Double));
	//安装信息叶
	JsonDecode::appendJsonDir(_root, "/install/", new JsonDirContent("yBias", &_installBias[0], QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/install/", new JsonDirContent("xBias", &_installBias[1], QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/install/", new JsonDirContent("zBias", &_installBias[2], QJsonValue::Double));
	//报文——开关信息叶
	JsonDecode::appendJsonDir(_root, "/msg/switch/", new JsonDirContent("uartMsg", &_uartMsg, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/switch/", new JsonDirContent("canMsg", &_canMsg, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/switch/", new JsonDirContent("usbMsg", &_usbMsg, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/switch/", new JsonDirContent("gyroMsg", &_gyroMsg, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/switch/", new JsonDirContent("accelMsg", &_accelMsg, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/switch/", new JsonDirContent("magMsg", &_magMsg, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/switch/", new JsonDirContent("presMsg", &_presMsg, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/switch/", new JsonDirContent("attitudeMsg", &_attitudeMsg, QJsonValue::Bool));
	//报文——转发开关叶
	JsonDecode::appendJsonDir(_root, "/msg/trans/", new JsonDirContent("usb_Can", &_usbCanTrans, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/trans/", new JsonDirContent("usb_Uart", &_usbUartTrans, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/trans/", new JsonDirContent("uart_Can", &_uartCanTrans, QJsonValue::Bool));
	//报文——开关信息叶
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("accelFusion", &_accelFusion, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("magFusion", &_magFusion, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("yawContinus", &_yawContinus, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("gyroType", &_gyroType, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("accelType", &_accelType, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("attitudeType", &_attitudeType, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("heightType", &_heightType, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("gyroLength", &_gyroLength, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("accelLength", &_accelLength, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("magLength", &_magLength, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/msg/format/", new JsonDirContent("attitudeLength", &_attitudeLength, QJsonValue::Bool));
	//传感器设置叶
	JsonDecode::appendJsonDir(_root, "/sensor/", new JsonDirContent("imuType", &_imuType, QJsonValue::String));
	JsonDecode::appendJsonDir(_root, "/sensor/", new JsonDirContent("gyroODR", &_gyroODR, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/sensor/", new JsonDirContent("accelODR", &_accelODR, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/sensor/", new JsonDirContent("attitudeODR", &_attitudeODR, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/sensor/", new JsonDirContent("magODR", &_magODR, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/sensor/", new JsonDirContent("heightODR", &_heightODR, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/sensor/", new JsonDirContent("gyroFSR", &_gyroFSR, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/sensor/", new JsonDirContent("accelFSR", &_accelFSR, QJsonValue::Double));
	//校准叶
	JsonDecode::appendJsonDir(_root, "/calibrate/set/", new JsonDirContent("gyroAllan", &_gyroAllan, QJsonValue::String));
	JsonDecode::appendJsonDir(_root, "/calibrate/set/", new JsonDirContent("accelHexahedron", &_sixFace, QJsonValue::String));
	JsonDecode::appendJsonDir(_root, "/calibrate/set/", new JsonDirContent("accelEllipsoid", &_accelEllipsoid, QJsonValue::String));
	JsonDecode::appendJsonDir(_root, "/calibrate/set/", new JsonDirContent("magEllipsoid", &_magEllipsoid, QJsonValue::String));

	JsonDecode::appendJsonDir(_root, "/calibrate/gyroBias/", new JsonDirContent("biasX", &_gyroBias[0], QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/calibrate/gyroBias/", new JsonDirContent("biasY", &_gyroBias[1], QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/calibrate/gyroBias/", new JsonDirContent("biasZ", &_gyroBias[2], QJsonValue::Double));

	JsonDecode::appendJsonDir(_root, "/calibrate/accelBias/", new JsonDirContent("biasX", &_accelBias[0], QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/calibrate/accelBias/", new JsonDirContent("biasY", &_accelBias[1], QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/calibrate/accelBias/", new JsonDirContent("biasZ", &_accelBias[2], QJsonValue::Double));

	JsonDecode::appendJsonDir(_root, "/calibrate/magBias/", new JsonDirContent("biasX", &_magBias[0], QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/calibrate/magBias/", new JsonDirContent("biasY", &_magBias[1], QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/calibrate/magBias/", new JsonDirContent("biasZ", &_magBias[2], QJsonValue::Double));

	//系统设置叶
	JsonDecode::appendJsonDir(_root, "/system/", new JsonDirContent("reset", &_reset, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/system/", new JsonDirContent("restore", &_restore, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/system/", new JsonDirContent("save", &_save, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/system/", new JsonDirContent("update", &_update, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/system/", new JsonDirContent("develop", &_develop, QJsonValue::Bool));
	JsonDecode::appendJsonDir(_root, "/system/", new JsonDirContent("bootVersion", &_bootVersion, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/system/", new JsonDirContent("appVersion", &_appVersion, QJsonValue::Double));
	//配置组设置叶
	JsonDecode::appendJsonDir(_root, "/", new JsonDirContent("setGroup", &_setGroup, QJsonValue::Double));
	
	//开发者参数
	//恒温PID叶
	JsonDecode::appendJsonDir(_root, "/develop/tem-pid/", new JsonDirContent("p", &_tempP, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/tem-pid/", new JsonDirContent("i", &_tempI, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/tem-pid/", new JsonDirContent("d", &_tempD, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/tem-pid/", new JsonDirContent("f", &_tempF, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/tem-pid/", new JsonDirContent("pm", &_tempPM, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/tem-pid/", new JsonDirContent("im", &_tempIM, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/tem-pid/", new JsonDirContent("dm", &_tempDM, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/tem-pid/", new JsonDirContent("om", &_tempOM, QJsonValue::Double));
	//ukf参数叶
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("accelBiasQ", &_ukfAccelBiasQ, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("gyroBiasQ", &_ukfGyroBiasQ, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("quatQ", &_ukfQuatQ, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("accelBiasV", &_ukfAccelBiasV, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("gyroBiasV", &_ukfGyroBiasV, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("rateV", &_ukfRateV, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("accelN", &_ukfAccN, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("distN", &_ukfDistN, QJsonValue::Double));
	JsonDecode::appendJsonDir(_root, "/develop/ukf/", new JsonDirContent("magN", &_ukfMagN, QJsonValue::Double));

	qRegisterMetaType<JsonDirContent>("JsonDirContent");

	QObject::connect(_connectThread->getDecode(), SIGNAL(stringDecode(QString)), this, SLOT(jsonStringDecode(QString)));
}

//析构函数
Config::~Config() {

}

void Config::jsonStringDecode(QString str) {
	//根据tree目录解析json
	JsonDecode::decodeString(str, _root);
}

//发送预备函数
QByteArray Config::sendConfigCommand(ConfigCommand cmd, QByteArray data) {
	uint8_t *array;
	uint8_t ptr = 0;
	int dataLength = data.length();
	uint8_t length = 6 + dataLength;
	array = new uint8_t[length];
	array[ptr++] = 0xAD;
	array[ptr++] = cmd;
	array[ptr++] = length;
	array[ptr++] = 0x00;
	for (uint8_t i = 0; i < dataLength; i++) {
		array[ptr++] = data[i];
	}
	CRC::AppendCrc8CheckSum(array, 4);
	CRC::AppendCrc16CheckSum(array, array[2]);
	QByteArray res((char*)array, array[2]);
	delete array;
	return res;
}

//在对应路径下的叶成员变更值后增加槽
void Config::addJsonDirSlot(QString path, const QObject *receive, const char *member) {
	Tree tree = JsonDecode::getTreeNodeByPaths(_root, path);
	JsonDirContent *content = (JsonDirContent *)getTreeData(tree);
	QObject::connect(content, SIGNAL(valueChanged(JsonDirContent)), receive, member);
}

//给叶成员添加控件
void Config::setJsonDirControl(QString path, QWidget *control, JsonDirContent::ConnectType connectType) {
	Tree tree = JsonDecode::getTreeNodeByPaths(_root, path);
	JsonDirContent *content = (JsonDirContent *)getTreeData(tree);
	content->setControl(control);
	content->setControlType(connectType);
	//如果存在需要被动响应的控件
	if (control != nullptr) {
		//map control -> tree
		activedMapping[control] = tree;
		//绑定或解绑控件主动槽
		if (connectType & JsonDirContent::activedResponse) {
			controlActiveUpdate(content, true);
		}
		//绑定或解绑控件被动槽
		if (connectType & JsonDirContent::passiveResponse) {
			QObject::connect(content, SIGNAL(valueChanged(JsonDirContent)), this, SLOT(controlPassiveUpdate(JsonDirContent)));
		}
	}
}

//控件主动改变json的连接槽
void Config::controlActiveUpdate(JsonDirContent *content, bool enable) {
	QString key = content->getKey();
	QWidget *control = content->getControl();
	QJsonValue::Type type = content->getType();
	QRegExp switchExp("(\\S+)Switch");
	QRegExp comboboxExp("(\\S+)ComboBox");
	QRegExp integerSpin("(\\S+)IntegerSpin");
	QRegExp doubleSpin("(\\S+)DoubleSpin");
	//如果存在需要被动响应的控件
	if (control != nullptr) {
		//分别对几类控件的主动响应槽进行解绑或绑定
		if (control->objectName().indexOf(switchExp) >= 0) {
			SwitchButton *swtBtn = (SwitchButton *)control;
			if (enable) {
				QObject::connect(swtBtn, SIGNAL(checkedChanged(bool)), this, SLOT(swtBtnActive(bool)));
			}
			else {
				QObject::disconnect(swtBtn, SIGNAL(checkedChanged(bool)), this, SLOT(swtBtnActive(bool)));
			}
		}
		else if (control->objectName().indexOf(comboboxExp) >= 0) {
			ComboBox *comboBox = (ComboBox *)control;
			if (enable) {
				QObject::connect(comboBox, SIGNAL(activated(QString)), this, SLOT(comboBoxActive(QString)));
			}
			else {
				QObject::disconnect(comboBox, SIGNAL(activated(QString)), this, SLOT(comboBoxActive(QString)));
			}
		}
		else if (control->objectName().indexOf(integerSpin) >= 0) {
			QSpinBox *spinBox = (QSpinBox *)control;
			if (enable) {
				QObject::connect(spinBox, SIGNAL(editingFinished()), this, SLOT(integerSpinActive()));
			}
			else {
				QObject::disconnect(spinBox, SIGNAL(editingFinished()), this, SLOT(integerSpinActive()));
			}
		}
		else if (control->objectName().indexOf(doubleSpin) >= 0) {
			QDoubleSpinBox *spinBox = (QDoubleSpinBox *)control;
			if (enable) {
				QObject::connect(spinBox, SIGNAL(editingFinished()), this, SLOT(doubleSpinActive()));
			}
			else {
				QObject::disconnect(spinBox, SIGNAL(editingFinished()), this, SLOT(doubleSpinActive()));
			}
		}
	}
}

//json被动触发控件槽
void Config::controlPassiveUpdate(JsonDirContent content) {
	QString key = content.getKey();
	QWidget *control = content.getControl();
	QJsonValue::Type type = content.getType();
	QRegExp switchExp("(\\S+)Switch");
	QRegExp comboboxExp("(\\S+)ComboBox");
	QRegExp integerSpin("(\\S+)IntegerSpin");
	QRegExp doubleSpin("(\\S+)DoubleSpin");
	QRegExp label("(\\S+)Display");
	//如果存在需要被动响应的控件
	if (control != nullptr) {
		//分别对几类控件的被动响应槽进行解绑或绑定
		if (control->objectName().indexOf(switchExp) >= 0) {
			SwitchButton *swtBtn = (SwitchButton *)control;
			if (type == QJsonValue::Bool) {
				bool *boolean = (bool *)content.getValue();
				swtBtn->setChecked(*boolean);
			}
		}
		else if (control->objectName().indexOf(comboboxExp) >= 0) {
			ComboBox *comboBox = (ComboBox *)control;
			if (type == QJsonValue::Double) {
				double *real = (double *)content.getValue();
				//使用正则表达式匹配
				QRegExp integerExp(QString("%1").arg(*real));
				for (int i = 0; i < comboBox->count(); i++) {
					if (comboBox->itemText(i).indexOf(integerExp) >= 0) {
						comboBox->setCurrentIndex(i);
						continue;
					}
				}
			}
			else if (type == QJsonValue::String) {
				QString *str = (QString *)content.getValue();
				comboBox->setCurrentText(*str);
			}
		}
		else if (control->objectName().indexOf(integerSpin) >= 0) {
			QSpinBox *spinBox = (QSpinBox *)control;
			if (type == QJsonValue::Double) {
				double *real = (double *)content.getValue();
				spinBox->setValue(*real);
			}
		}
		else if (control->objectName().indexOf(doubleSpin) >= 0) {
			QDoubleSpinBox *spinBox = (QDoubleSpinBox *)control;
			if (type == QJsonValue::Double) {
				double *real = (double *)content.getValue();
				spinBox->setValue(*real);
			}
		}
		else if (control->objectName().indexOf(label) >= 0) {
			QLabel *label = (QLabel *)control;
			if (type == QJsonValue::Double) {
				double *real = (double *)content.getValue();
				label->setText(QString("%1").arg(*real));
			}
			else if (type == QJsonValue::Bool) {
				bool *boolean = (bool *)content.getValue();
				label->setText(QString("%1").arg(*boolean));
			}
			else if (type == QJsonValue::String) {
				QString *str = (QString *)content.getValue();
				label->setText(*str);
			}
		}
	}
}

//连接/断开全部叶子的控件信号槽
void Config::connectAllLeaves(Tree T, bool enable) {
	int childLength = getTreeChildrenLength(T);
	for (int j = 0; j < childLength; j++) {
		Tree child = atParentTree(T, j);
		JsonDirContent *jsonDir = (JsonDirContent *)getTreeData(child);
		QJsonValue::Type type = jsonDir->getType();
		QWidget *control = jsonDir->getControl();
		JsonDirContent::ConnectType connectType = jsonDir->getConnectType();
		if (type == QJsonValue::Object) {
			connectAllLeaves(child, enable);
		}
		else {
			//如果存在需要被动响应的控件
			if (control != nullptr) {
				//map control -> tree
				activedMapping[control] = child;
				//绑定或解绑控件主动槽
				if (connectType & JsonDirContent::activedResponse) {
					controlActiveUpdate(jsonDir, enable);
				}
				//绑定或解绑控件被动槽
				if (connectType & JsonDirContent::passiveResponse) {
					if (enable) {
						QObject::connect(jsonDir, SIGNAL(valueChanged(JsonDirContent)), this, SLOT(controlPassiveUpdate(JsonDirContent)));
					}
					else {
						QObject::disconnect(jsonDir, SIGNAL(valueChanged(JsonDirContent)), this, SLOT(controlPassiveUpdate(JsonDirContent)));
					}
				}
			}
		}
	}
}

//switchButton改变时的响应槽
void Config::swtBtnActive(bool checked) {
	SwitchButton *swtBtn = (SwitchButton *)sender();
	if (swtBtn->isEnabled()) {
		//获取对应Tree和对应的JsonDirContent
		Tree tree = activedMapping[swtBtn];
		bool *boolean = JsonDecode::getTreeValue<bool>(tree);
		*boolean = checked;
		//获取对应map下的完整json路径
		QByteArray jsonByte = JsonDecode::getCompleteDir(tree);
		//qDebug() << jsonByte;
		QByteArray txArray = Config::sendConfigCommand(Config::JsonConfig, jsonByte.data());
		_connectThread->appendTx(&txArray);
	}
}

//comboBox改变时的响应槽
void Config::comboBoxActive(QString selected) {
	ComboBox *box = (ComboBox *)sender();
	if (box->isEnabled()) {
		//获取对应Tree和对应的JsonDirContent
		Tree tree = activedMapping[box];
		QJsonValue::Type type = JsonDecode::getTreeType(tree);
		//根据控件改变值
		if (type == QJsonValue::String) {
			QString *str = JsonDecode::getTreeValue<QString>(tree);
			*str = selected;
		}
		else if (type == QJsonValue::Double) {
			double *real = JsonDecode::getTreeValue<double>(tree);
			QRegExp integerExp("(\\d+)");
			if (selected.indexOf(integerExp) >= 0) {
				*real = integerExp.cap(1).toDouble();
			}
		}
		//获取对应map下的完整json路径
		QByteArray jsonByte = JsonDecode::getCompleteDir(tree);
		//qDebug() << jsonByte;
		QByteArray txArray = Config::sendConfigCommand(Config::JsonConfig, jsonByte);
		_connectThread->appendTx(&txArray);
	}
}

//qSpinBox改变时的响应槽
void Config::integerSpinActive() {
	QSpinBox *box = (QSpinBox *)sender();
	if (box->isEnabled()) {
		//获取对应Tree和对应的JsonDirContent
		Tree tree = activedMapping[box];
		double *real = JsonDecode::getTreeValue<double>(tree);
		*real = box->value();
		//获取对应map下的完整json路径
		QByteArray jsonByte = JsonDecode::getCompleteDir(tree);
		//qDebug() << jsonByte;
		QByteArray txArray = Config::sendConfigCommand(Config::JsonConfig, jsonByte);
		_connectThread->appendTx(&txArray);
	}
}

//qDoubleSpinBox改变时的响应槽
void Config::doubleSpinActive() {
	QDoubleSpinBox *box = (QDoubleSpinBox *)sender();
	if (box->isEnabled()) {
		//获取对应Tree和对应的JsonDirContent
		Tree tree = activedMapping[box];
		double *real = JsonDecode::getTreeValue<double>(tree);
		*real = box->value();
		//获取对应map下的完整json路径
		QByteArray jsonByte = JsonDecode::getCompleteDir(tree);
		//qDebug() << jsonByte;
		QByteArray txArray = Config::sendConfigCommand(Config::JsonConfig, jsonByte);
		_connectThread->appendTx(&txArray);
	}
}

//设置某树叶的值并发送完整路径Json
void Config::sendJsonDirValue(QString path, void *value) {
	Tree tree = JsonDecode::getTreeNodeByPaths(_root, path);
	JsonDirContent *content = (JsonDirContent *)getTreeData(tree);
	QJsonValue::Type valueType = content->getType();
	switch (valueType) {
		case QJsonValue::Bool: {
			bool *boolean = (bool *)content->getValue();
			*boolean = *(bool *)value;
			break;
		}
		case QJsonValue::Double: {
			double *real = (double *)content->getValue();
			*real = *(double *)value;
			break;
		}
		case QJsonValue::String: {
			QString *str = (QString *)content->getValue();
			*str = *(QString *)value;
			break;
		}
	}
	QByteArray txArray = Config::sendConfigCommand(Config::JsonConfig, JsonDecode::getCompleteDir(tree));
	qDebug() << "send:" << JsonDecode::getCompleteDir(tree);
	_connectThread->appendTx(&txArray);
}

//发送获取某树叶值的完整路径Json
void Config::getJsonDirValue(QString path) {
	Tree tree = JsonDecode::getTreeNodeByPaths(_root, path);
	JsonDirContent *content = (JsonDirContent *)getTreeData(tree);
	QByteArray txArray = Config::sendConfigCommand(Config::JsonConfig, JsonDecode::getSomewhereDirData(tree));
	qDebug() << "send:" << JsonDecode::getSomewhereDirData(tree);
	_connectThread->appendTx(&txArray);
}


